/**
 * 高级电子表格编辑器
 * 基于MIT许可证的开源库实现
 *
 * 依赖:
 * - x-spreadsheet: https://github.com/myliang/x-spreadsheet (MIT)
 * - SheetJS: https://github.com/SheetJS/sheetjs (Apache-2.0)
 *
 * 版本: 1.1.0
 * 更新日期: 2025-03-18
 */
class SpreadsheetEditor {
    /**
     * 创建电子表格编辑器实例
     * @param {string|HTMLElement} container - 容器元素或选择器
     * @param {Object} options - 配置选项
     */
    constructor(container, options = {}) {
        // 确保容器元素存在
        this.container = typeof container === "string" ? document.querySelector(container) : container

        if (!this.container) {
            throw new Error("Container element not found")
        }

        // 事件回调
        this.eventHandlers = {
            change: [],
            ready: [],
            error: [],
        }

        // 当前语言
        this.currentLang = "zh-CN"

        // 默认配置
        this.options = Object.assign(
            {
                showToolbar: true,
                showGrid: true,
                showContextmenu: true,
                view: {
                    height: () => this.container.clientHeight || 500,
                    width: () => this.container.clientWidth || 800,
                },
                row: {
                    len: 100,
                    height: 25,
                },
                col: {
                    len: 26,
                    width: 100,
                    indexWidth: 60,
                    minWidth: 60,
                },
                style: {
                    bgcolor: "#ffffff",
                    color: "#333333",
                    align: "left",
                    valign: "middle",
                    textwrap: false,
                    strike: false,
                    underline: false,
                    fontsize: 10,
                    fontname: "Arial",
                    bold: false,
                    italic: false,
                },
            },
            options,
        )

        // 初始数据
        this.initialData = null

        // 创建文件输入元素用于导入Excel
        this.fileInput = document.createElement("input")
        this.fileInput.type = "file"
        this.fileInput.accept = ".xlsx, .xls"
        this.fileInput.style.display = "none"
        this.fileInput.addEventListener("change", this.handleFileSelect.bind(this))
        document.body.appendChild(this.fileInput)

        // 加载依赖并初始化
        this.loadDependencies()
            .then(() => {
                this.init()
                this.triggerEvent("ready", this)
            })
            .catch((error) => {
                console.error("加载依赖失败:", error)
                this.triggerEvent("error", { type: "init", error })
            })
    }

    /**
     * 加载依赖库
     * @returns {Promise} 加载完成的Promise
     */
    async loadDependencies() {
        // 检查是否已加载依赖
        if (window.x_spreadsheet && window.XLSX) {
            return Promise.resolve()
        }

        // 加载CSS
        if (!document.querySelector('link[href*="x-spreadsheet.css"]')) {
            const link = document.createElement("link")
            link.rel = "stylesheet"
            link.href = "https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css"
            document.head.appendChild(link)
        }

        // 加载JS
        const loadScript = (src) => {
            return new Promise((resolve, reject) => {
                if (document.querySelector(`script[src*="${src}"]`)) {
                    resolve()
                    return
                }

                const script = document.createElement("script")
                script.src = src
                script.onload = resolve
                script.onerror = reject
                document.head.appendChild(script)
            })
        }

        // 并行加载脚本
        await Promise.all([
            loadScript("https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.js"),
            loadScript("https://unpkg.com/xlsx@0.18.5/dist/xlsx.full.min.js"),
        ])

        // 等待一小段时间确保脚本完全加载
        return new Promise((resolve) => setTimeout(resolve, 300))
    }

    /**
     * 初始化电子表格
     */
    init() {
        if (!window.x_spreadsheet) {
            console.error("x-spreadsheet 未加载")
            this.triggerEvent("error", { type: "init", error: new Error("x-spreadsheet 未加载") })
            return
        }

        // 设置本地化
        this.setupLocalization()

        // 创建电子表格实例
        this.xs = window.x_spreadsheet(this.container, this.options)

        // 加载默认数据
        this.xs.loadData({
            // 默认数据
            name: "Sheet1",
            freeze: "A1",
            styles: [
                {
                    bgcolor: "#f4f5f8",
                    textwrap: true,
                    color: "#900b09",
                    border: {
                        top: ["thin", "#0366d6"],
                        bottom: ["thin", "#0366d6"],
                        right: ["thin", "#0366d6"],
                        left: ["thin", "#0366d6"],
                    },
                },
            ],
            merges: [],
            rows: {},
            cols: {
                len: 26,
            },
            validations: [],
            autofilter: {},
        })

        // 添加数据变更事件
        this.xs.change((data) => {
            // 数据变更回调
            this.triggerEvent("change", data)
        })

        // 如果有初始数据，加载它
        if (this.initialData) {
            setTimeout(() => {
                this.setData(this.initialData)
                this.initialData = null
            }, 100)
        }

        // 扩展功能
        this.extendFunctionality()
    }

    /**
     * 设置本地化
     */
    setupLocalization() {
        // 定义语言包
        this.locales = {
            "zh-CN": {
                toolbar: {
                    undo: "撤销",
                    redo: "重做",
                    print: "打印",
                    paintformat: "格式刷",
                    clearformat: "清除格式",
                    format: "数据格式",
                    fontName: "字体",
                    fontSize: "字号",
                    fontBold: "加粗",
                    fontItalic: "斜体",
                    underline: "下划线",
                    strike: "删除线",
                    textColor: "文字颜色",
                    fillColor: "填充颜色",
                    border: "边框",
                    merge: "合并单元格",
                    align: "水平对齐",
                    valign: "垂直对齐",
                    textwrap: "自动换行",
                    freeze: "冻结",
                    formula: "函数",
                    more: "更多",
                },
                contextmenu: {
                    copy: "复制",
                    cut: "剪切",
                    paste: "粘贴",
                    pasteValue: "粘贴值",
                    pasteFormat: "粘贴格式",
                    hide: "隐藏",
                    insertRow: "插入行",
                    insertColumn: "插入列",
                    deleteRow: "删除行",
                    deleteColumn: "删除列",
                    deleteCell: "删除单元格",
                    deleteCellText: "删除内容",
                    validation: "数据验证",
                    customStyle: "设置样式",
                    mergeCells: "合并单元格",
                    unmergeCells: "取消合并",
                },
                button: {
                    confirm: "确认",
                    cancel: "取消",
                },
                sort: {
                    desc: "降序",
                    asc: "升序",
                },
                dialog: {
                    styleHeader: "单元格样式",
                    textColor: "文字颜色:",
                    bgColor: "背景颜色:",
                    fontWeight: "字体粗细:",
                    fontStyle: "字体样式:",
                    normal: "正常",
                    bold: "粗体",
                    italic: "斜体",
                    apply: "应用",
                    cancel: "取消",
                },
            },
            "en-US": {
                toolbar: {
                    undo: "Undo",
                    redo: "Redo",
                    print: "Print",
                    paintformat: "Format painter",
                    clearformat: "Clear format",
                    format: "Format",
                    fontName: "Font",
                    fontSize: "Font size",
                    fontBold: "Bold",
                    fontItalic: "Italic",
                    underline: "Underline",
                    strike: "Strike through",
                    textColor: "Text color",
                    fillColor: "Fill color",
                    border: "Border",
                    merge: "Merge cells",
                    align: "Horizontal align",
                    valign: "Vertical align",
                    textwrap: "Text wrap",
                    freeze: "Freeze",
                    formula: "Formula",
                    more: "More",
                },
                contextmenu: {
                    copy: "Copy",
                    cut: "Cut",
                    paste: "Paste value",
                    pasteFormat: "Paste format",
                    hide: "Hide",
                    insertRow: "Insert row",
                    insertColumn: "Insert column",
                    deleteRow: "Delete row",
                    deleteColumn: "Delete column",
                    deleteCell: "Delete cell",
                    deleteCellText: "Delete text",
                    validation: "Data validation",
                    customStyle: "Custom style",
                    mergeCells: "Merge cells",
                    unmergeCells: "Unmerge cells",
                },
                button: {
                    confirm: "Confirm",
                    cancel: "Cancel",
                },
                sort: {
                    desc: "Sort Z-A",
                    asc: "Sort A-Z",
                },
                dialog: {
                    styleHeader: "Cell Style",
                    textColor: "Text color:",
                    bgColor: "Background color:",
                    fontWeight: "Font weight:",
                    fontStyle: "Font style:",
                    normal: "Normal",
                    bold: "Bold",
                    italic: "Italic",
                    apply: "Apply",
                    cancel: "Cancel",
                },
            },
        }

        // 设置x-spreadsheet的本地化
        if (window.x_spreadsheet && window.x_spreadsheet.locale) {
            // 注册中文语言包
            window.x_spreadsheet.locale("zh-cn", {
                toolbar: {
                    undo: this.locales["zh-CN"].toolbar.undo,
                    redo: this.locales["zh-CN"].toolbar.redo,
                    print: this.locales["zh-CN"].toolbar.print,
                    paintformat: this.locales["zh-CN"].toolbar.paintformat,
                    clearformat: this.locales["zh-CN"].toolbar.clearformat,
                    format: this.locales["zh-CN"].toolbar.format,
                    fontName: this.locales["zh-CN"].toolbar.fontName,
                    fontSize: this.locales["zh-CN"].toolbar.fontSize,
                    fontBold: this.locales["zh-CN"].toolbar.fontBold,
                    fontItalic: this.locales["zh-CN"].toolbar.fontItalic,
                    underline: this.locales["zh-CN"].toolbar.underline,
                    strike: this.locales["zh-CN"].toolbar.strike,
                    textColor: this.locales["zh-CN"].toolbar.textColor,
                    fillColor: this.locales["zh-CN"].toolbar.fillColor,
                    border: this.locales["zh-CN"].toolbar.border,
                    merge: this.locales["zh-CN"].toolbar.merge,
                    align: this.locales["zh-CN"].toolbar.align,
                    valign: this.locales["zh-CN"].toolbar.valign,
                    textwrap: this.locales["zh-CN"].toolbar.textwrap,
                    freeze: this.locales["zh-CN"].toolbar.freeze,
                    formula: this.locales["zh-CN"].toolbar.formula,
                    more: this.locales["zh-CN"].toolbar.more,
                },
                contextmenu: {
                    copy: this.locales["zh-CN"].contextmenu.copy,
                    cut: this.locales["zh-CN"].contextmenu.cut,
                    paste: this.locales["zh-CN"].contextmenu.paste,
                    pasteValue: this.locales["zh-CN"].contextmenu.pasteValue,
                    pasteFormat: this.locales["zh-CN"].contextmenu.pasteFormat,
                    hide: this.locales["zh-CN"].contextmenu.hide,
                    insertRow: this.locales["zh-CN"].contextmenu.insertRow,
                    insertColumn: this.locales["zh-CN"].contextmenu.insertColumn,
                    deleteRow: this.locales["zh-CN"].contextmenu.deleteRow,
                    deleteColumn: this.locales["zh-CN"].contextmenu.deleteColumn,
                    deleteCell: this.locales["zh-CN"].contextmenu.deleteCell,
                    deleteCellText: this.locales["zh-CN"].contextmenu.deleteCellText,
                    validation: this.locales["zh-CN"].contextmenu.validation,
                },
                button: {
                    confirm: this.locales["zh-CN"].button.confirm,
                    cancel: this.locales["zh-CN"].button.cancel,
                },
                sort: {
                    desc: this.locales["zh-CN"].sort.desc,
                    asc: this.locales["zh-CN"].sort.asc,
                },
            })

            // 设置默认语言
            window.x_spreadsheet.locale("zh-cn")
        }
    }

    /**
     * 切换语言
     * @param {string} lang - 语言代码 ('zh-CN' 或 'en-US')
     */
    setLanguage(lang) {
        if (!this.locales[lang]) {
            console.error(`不支持的语言: ${lang}`)
            return
        }

        this.currentLang = lang

        // 设置x-spreadsheet的语言
        if (this.xs && window.x_spreadsheet && window.x_spreadsheet.locale) {
            if (lang === "zh-CN") {
                window.x_spreadsheet.locale("zh-cn")
            } else if (lang === "en-US") {
                window.x_spreadsheet.locale("en")
            }

            // 重新加载以应用新语言
            const data = this.xs.getData()
            this.xs.loadData(data)
        }

        // 更新自定义菜单项
        this.updateContextMenuLocalization()
    }

    /**
     * 更新右键菜单本地化
     */
    updateContextMenuLocalization() {
        if (!this.xs || !this.xs.contextmenu) return

        const contextMenu = this.xs.contextmenu
        const locale = this.locales[this.currentLang]

        // 移除旧的自定义菜单项
        try {
            contextMenu.removeItem("custom-style")
            contextMenu.removeItem("merge-cells")
            contextMenu.removeItem("unmerge-cells")
        } catch (e) {
            // 忽略错误，可能是菜单项不存在
        }

        // 添加新的本地化菜单项
        contextMenu.addItem("custom-style", locale.contextmenu.customStyle, () => {
            this.openStyleDialog()
        })

        contextMenu.addItem("merge-cells", locale.contextmenu.mergeCells, () => {
            this.xs.merge()
        })

        contextMenu.addItem("unmerge-cells", locale.contextmenu.unmergeCells, () => {
            this.xs.unmerge()
        })
    }

    /**
     * 扩展功能
     */
    extendFunctionality() {
        if (!this.xs) return

        // 扩展右键菜单
        this.updateContextMenuLocalization()
    }

    /**
     * 打开样式对话框
     */
    openStyleDialog() {
        const locale = this.locales[this.currentLang]

        // 简单的样式对话框实现
        const dialog = document.createElement("div")
        dialog.className = "xs-style-dialog"
        dialog.innerHTML = `
      <div class="xs-style-dialog-content">
        <h3>${locale.dialog.styleHeader}</h3>
        <div class="xs-style-options">
          <div class="xs-style-option">
            <label>${locale.dialog.textColor}</label>
            <input type="color" id="font-color" value="#000000">
          </div>
          <div class="xs-style-option">
            <label>${locale.dialog.bgColor}</label>
            <input type="color" id="bg-color" value="#ffffff">
          </div>
          <div class="xs-style-option">
            <label>${locale.dialog.fontWeight}</label>
            <select id="font-weight">
              <option value="normal">${locale.dialog.normal}</option>
              <option value="bold">${locale.dialog.bold}</option>
            </select>
          </div>
          <div class="xs-style-option">
            <label>${locale.dialog.fontStyle}</label>
            <select id="font-style">
              <option value="normal">${locale.dialog.normal}</option>
              <option value="italic">${locale.dialog.italic}</option>
            </select>
          </div>
        </div>
        <div class="xs-style-buttons">
          <button id="apply-style">${locale.dialog.apply}</button>
          <button id="cancel-style">${locale.dialog.cancel}</button>
        </div>
      </div>
    `

        document.body.appendChild(dialog)

        // 添加样式
        const style = document.createElement("style")
        style.textContent = `
      .xs-style-dialog {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.5);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10000;
      }
      .xs-style-dialog-content {
        background: white;
        padding: 20px;
        border-radius: 4px;
        min-width: 300px;
      }
      .xs-style-options {
        margin: 15px 0;
      }
      .xs-style-option {
        margin: 10px 0;
        display: flex;
        justify-content: space-between;
      }
      .xs-style-buttons {
        display: flex;
        justify-content: flex-end;
        gap: 10px;
        margin-top: 15px;
      }
      .xs-style-buttons button {
        padding: 5px 15px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
      #apply-style {
        background: #4285f4;
        color: white;
      }
      #cancel-style {
        background: #f1f3f4;
      }
    `
        document.head.appendChild(style)

        // 绑定事件
        const applyBtn = dialog.querySelector("#apply-style")
        const cancelBtn = dialog.querySelector("#cancel-style")
        const fontColorInput = dialog.querySelector("#font-color")
        const bgColorInput = dialog.querySelector("#bg-color")
        const fontWeightSelect = dialog.querySelector("#font-weight")
        const fontStyleSelect = dialog.querySelector("#font-style")

        applyBtn.addEventListener("click", () => {
            const style = {
                color: fontColorInput.value,
                bgcolor: bgColorInput.value,
                bold: fontWeightSelect.value === "bold",
                italic: fontStyleSelect.value === "italic",
            }

            this.xs.cellStyle(style)
            document.body.removeChild(dialog)
            document.head.removeChild(style)
        })

        cancelBtn.addEventListener("click", () => {
            document.body.removeChild(dialog)
            document.head.removeChild(style)
        })
    }

    /**
     * 导入Excel
     */
    importExcel() {
        this.fileInput.click()
    }

    /**
     * 处理文件选择
     * @param {Event} event - 文件选择事件
     */
    handleFileSelect(event) {
        const file = event.target.files[0]
        if (!file) return

        const reader = new FileReader()

        reader.onload = (e) => {
            try {
                const data = new Uint8Array(e.target.result)
                // 确保XLSX已定义
                if (typeof XLSX === "undefined") {
                    console.error("XLSX is not defined. Ensure the library is loaded.")
                    this.triggerEvent("error", { type: "import", error: new Error("XLSX library is not loaded") })
                    alert("XLSX library is not loaded. Please check your dependencies.")
                    return
                }

                // 读取Excel文件
                const workbook = XLSX.read(data, { type: "array", cellStyles: true })

                // 转换为x-spreadsheet格式
                const output = this.convertExcelToXSpreadsheet(workbook)

                // 加载数据
                if (this.xs) {
                    this.xs.loadData(output)
                    this.triggerEvent("change", output)
                }
            } catch (error) {
                console.error("导入Excel失败:", error)
                this.triggerEvent("error", { type: "import", error })
                alert("导入Excel失败，请检查文件格式是否正确。")
            }
        }

        reader.readAsArrayBuffer(file)
        this.fileInput.value = "" // 重置文件输入，允许再次选择相同文件
    }

    /**
     * 将Excel转换为x-spreadsheet格式
     * @param {Object} workbook - XLSX工作簿
     * @returns {Object} x-spreadsheet格式的数据
     */
    convertExcelToXSpreadsheet(workbook) {
        // 确保工作簿存在
        if (!workbook || !workbook.SheetNames || !workbook.SheetNames.length) {
            console.error("无效的Excel工作簿")
            return {
                name: "Sheet1",
                rows: {},
                cols: {},
                merges: [],
                validations: [],
                autofilter: {},
            }
        }

        const sheetName = workbook.SheetNames[0]
        const worksheet = workbook.Sheets[sheetName]

        // 获取工作表范围
        const range = XLSX.utils.decode_range(worksheet["!ref"] || "A1:A1")

        // 创建x-spreadsheet格式的数据
        const result = {
            name: sheetName,
            freeze: "A1",
            styles: [],
            merges: [],
            rows: {},
            cols: {
                len: Math.max(26, range.e.c + 1),
            },
            validations: [],
            autofilter: {},
        }

        // 处理合并单元格
        if (worksheet["!merges"]) {
            worksheet["!merges"].forEach((merge) => {
                const startCell = XLSX.utils.encode_cell({ r: merge.s.r, c: merge.s.c })
                const endCell = XLSX.utils.encode_cell({ r: merge.e.r, c: merge.e.c })
                result.merges.push(`${startCell}:${endCell}`)
            })
        }

        // 处理列宽
        if (worksheet["!cols"]) {
            worksheet["!cols"].forEach((col, index) => {
                if (col && col.width) {
                    if (!result.cols.len) result.cols = { len: 26 }
                    if (!result.cols[index]) result.cols[index] = {}
                    // 转换Excel列宽到像素 (大约的转换)
                    result.cols[index].width = Math.round(col.width * 8)
                }
            })
        }

        // 处理行高
        if (worksheet["!rows"]) {
            worksheet["!rows"].forEach((row, index) => {
                if (row && row.hpt) {
                    if (!result.rows[index]) result.rows[index] = { cells: {} }
                    // 转换Excel行高到像素 (大约的转换)
                    result.rows[index].height = Math.round(row.hpt * 1.3333)
                }
            })
        }

        // 创建样式映射
        const styleMap = new Map()

        // 处理单元格数据和样式
        for (let r = range.s.r; r <= range.e.r; r++) {
            for (let c = range.s.c; c <= range.e.c; c++) {
                const cellAddress = XLSX.utils.encode_cell({ r, c })
                const cell = worksheet[cellAddress]

                if (!cell) continue

                if (!result.rows[r]) {
                    result.rows[r] = { cells: {} }
                }

                // 基本单元格数据
                const cellData = { text: "" }

                // 处理单元格值
                if (cell.v !== undefined) {
                    if (cell.t === "n") {
                        // 数字
                        cellData.text = String(cell.v)
                    } else if (cell.t === "b") {
                        // 布尔值
                        cellData.text = cell.v ? "TRUE" : "FALSE"
                    } else if (cell.t === "d") {
                        // 日期
                        cellData.text = new Date(cell.v).toLocaleDateString()
                    } else {
                        // 字符串或其他
                        cellData.text = String(cell.v)
                    }
                }

                // 处理公式
                if (cell.f) {
                    cellData.formula = cell.f
                }

                // 处理样式
                if (cell.s) {
                    let styleId = -1

                    // 检查是否已有相同样式
                    const styleKey = JSON.stringify(cell.s)
                    if (styleMap.has(styleKey)) {
                        styleId = styleMap.get(styleKey)
                    } else {
                        // 创建新样式
                        const style = {}

                        // 字体
                        if (cell.s.font) {
                            if (cell.s.font.bold) style.bold = true
                            if (cell.s.font.italic) style.italic = true
                            if (cell.s.font.underline) style.underline = true
                            if (cell.s.font.strike) style.strike = true
                            if (cell.s.font.color && cell.s.font.color.rgb) {
                                style.color = `#${cell.s.font.color.rgb}`
                            }
                            if (cell.s.font.name) style.fontname = cell.s.font.name
                            if (cell.s.font.sz) style.fontsize = cell.s.font.sz
                        }

                        // 填充
                        if (cell.s.fill && cell.s.fill.fgColor && cell.s.fill.fgColor.rgb) {
                            style.bgcolor = `#${cell.s.fill.fgColor.rgb}`
                        }

                        // 对齐
                        if (cell.s.alignment) {
                            if (cell.s.alignment.horizontal) {
                                style.align = cell.s.alignment.horizontal
                            }
                            if (cell.s.alignment.vertical) {
                                style.valign = cell.s.alignment.vertical
                            }
                            if (cell.s.alignment.wrapText) {
                                style.textwrap = true
                            }
                        }

                        // 边框
                        if (cell.s.border) {
                            style.border = {}
                            ;["top", "bottom", "left", "right"].forEach((side) => {
                                if (cell.s.border[side] && cell.s.border[side].style) {
                                    const borderStyle = cell.s.border[side].style
                                    const borderColor =
                                        cell.s.border[side].color && cell.s.border[side].color.rgb
                                            ? `#${cell.s.border[side].color.rgb}`
                                            : "#000000"
                                    style.border[side] = [borderStyle, borderColor]
                                }
                            })
                        }

                        // 添加样式到样式列表
                        styleId = result.styles.length
                        result.styles.push(style)
                        styleMap.set(styleKey, styleId)
                    }

                    // 应用样式到单元格
                    if (styleId >= 0) {
                        cellData.style = styleId
                    }
                }

                // 添加单元格数据
                result.rows[r].cells[c] = cellData
            }
        }

        return result
    }

    // 修复导出Excel方法中的空对象错误
    /**
     * 导出Excel
     * @param {string} filename - 文件名
     */
    exportExcel(filename = "spreadsheet.xlsx") {
        if (!this.xs) {
            console.error("电子表格未初始化")
            return
        }

        try {
            // 获取电子表格数据
            const data = this.xs.getData()
            console.log("导出数据:", data)

            // 检查数据有效性
            if (!data || !data.rows) {
                throw new Error("无效的电子表格数据")
            }

            // 创建二维数组表示数据
            const arrayData = this.convertToArrayData(data)

            // 创建工作簿和工作表
            const wb = XLSX.utils.book_new()
            const ws = XLSX.utils.aoa_to_sheet(arrayData)

            // 处理合并单元格
            if (data.merges && Array.isArray(data.merges) && data.merges.length > 0) {
                ws["!merges"] = data.merges.map((merge) => {
                    const [start, end] = merge.split(":")
                    const startCell = XLSX.utils.decode_cell(start)
                    const endCell = XLSX.utils.decode_cell(end)
                    return { s: startCell, e: endCell }
                })
            }

            // 处理列宽
            if (data.cols) {
                ws["!cols"] = []
                const colLen = data.cols.len || 26

                for (let i = 0; i < colLen; i++) {
                    if (data.cols[i] && data.cols[i].width) {
                        ws["!cols"][i] = { width: data.cols[i].width / 8 } // 转换像素到Excel列宽
                    } else {
                        ws["!cols"][i] = { width: 8.43 } // 默认列宽
                    }
                }
            }

            // 处理行高
            ws["!rows"] = []
            if (data.rows && typeof data.rows === "object") {
                Object.keys(data.rows).forEach((rowKey) => {
                    const rowIndex = Number.parseInt(rowKey, 10)
                    const row = data.rows[rowKey]

                    if (row && row.height) {
                        ws["!rows"][rowIndex] = { hpt: row.height / 1.3333 } // 转换像素到Excel行高
                    }
                })
            }

            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, data.name || "Sheet1")

            // 导出文件
            XLSX.writeFile(wb, filename)
            this.triggerEvent("export", { filename })
        } catch (error) {
            console.error("导出Excel失败:", error)
            this.triggerEvent("error", { type: "export", error })
            alert("导出Excel失败: " + error.message)
        }
    }

    /**
     * 将x-spreadsheet数据转换为二维数组
     * @param {Object} data - x-spreadsheet数据
     * @returns {Array} 二维数组数据
     */
    convertToArrayData(data) {
        if (!data || !data.rows || typeof data.rows !== "object") {
            return [[]] // 返回一个空的二维数组
        }

        // 找出最大行列
        let maxRow = 0
        let maxCol = 0

        Object.keys(data.rows).forEach((rowKey) => {
            const rowIndex = Number.parseInt(rowKey, 10)
            const cells = data.rows[rowKey]?.cells || {}

            if (typeof cells === "object") {
                Object.keys(cells).forEach((colKey) => {
                    const colIndex = Number.parseInt(colKey, 10)
                    maxRow = Math.max(maxRow, rowIndex)
                    maxCol = Math.max(maxCol, colIndex)
                })
            }
        })

        // 创建空二维数组
        const arrayData = []
        for (let i = 0; i <= maxRow; i++) {
            arrayData[i] = []
            for (let j = 0; j <= maxCol; j++) {
                arrayData[i][j] = null
            }
        }

        // 填充数据
        Object.keys(data.rows).forEach((rowKey) => {
            const rowIndex = Number.parseInt(rowKey, 10)
            const cells = data.rows[rowKey]?.cells

            if (cells && typeof cells === "object") {
                Object.keys(cells).forEach((colKey) => {
                    const colIndex = Number.parseInt(colKey, 10)
                    const cell = cells[colKey]

                    if (cell && cell.text !== undefined) {
                        arrayData[rowIndex][colIndex] = cell.text
                    }
                })
            }
        })

        return arrayData
    }

    /**
     * 将x-spreadsheet数据转换为Excel格式
     * @param {Object} data - x-spreadsheet数据
     * @returns {Object} XLSX工作簿
     */
    /*convertXSpreadsheetToExcel(data) {
          // 检查数据有效性
          if (!data) {
              console.error('无效的电子表格数据');
              return null;
          }

          // 创建新的工作簿
          const wb = XLSX.utils.book_new();

          try {
              // 提取数据到二维数组
              const rows = data.rows || {};
              const styles = data.styles || [];
              const merges = data.merges || [];

              // 找出最大行列
              let maxRow = 0;
              let maxCol = 0;

              Object.keys(rows).forEach(rowKey => {
                  const rowIndex = parseInt(rowKey, 10);
                  const cells = rows[rowKey]?.cells || {};

                  Object.keys(cells).forEach(colKey => {
                      const colIndex = parseInt(colKey, 10);
                      maxRow = Math.max(maxRow, rowIndex);
                      maxCol = Math.max(maxCol, colIndex);
                  });
              });

              // 创建工作表
              const ws = XLSX.utils.aoa_to_sheet([]);

              // 设置工作表范围
              ws['!ref'] = XLSX.utils.encode_range({
                  s: { r: 0, c: 0 },
                  e: { r: maxRow, c: maxCol }
              });

              // 填充数据和样式
              Object.keys(rows).forEach(rowKey => {
                  const rowIndex = parseInt(rowKey, 10);
                  const row = rows[rowKey];
                  const cells = row?.cells || {};

                  // 设置行高
                  if (row.height) {
                      if (!ws['!rows']) ws['!rows'] = [];
                      ws['!rows'][rowIndex] = { hpt: row.height / 1.3333 }; // 转换像素到Excel行高
                  }

                  Object.keys(cells).forEach(colKey => {
                      const colIndex = parseInt(colKey, 10);
                      const cell = cells[colKey];

                      if (!cell) return;

                      // 创建Excel单元格
                      const cellAddress = XLSX.utils.encode_cell({ r: rowIndex, c: colIndex });
                      const xlsxCell = { t: 's', v: cell.text || '' };

                      // 处理公式
                      if (cell.formula) {
                          xlsxCell.f = cell.formula;
                      }

                      // 处理样式
                      if (cell.style !== undefined && styles[cell.style]) {
                          const style = styles[cell.style];
                          xlsxCell.s = {};

                          // 字体
                          xlsxCell.s.font = {};
                          if (style.bold) xlsxCell.s.font.bold = true;
                          if (style.italic) xlsxCell.s.font.italic = true;
                          if (style.underline) xlsxCell.s.font.underline = true;
                          if (style.strike) xlsxCell.s.font.strike = true;
                          if (style.color) xlsxCell.s.font.color = { rgb: style.color.replace('#', '') };
                          if (style.fontname) xlsxCell.s.font.name = style.fontname;
                          if (style.fontsize) xlsxCell.s.font.sz = style.fontsize;

                          // 填充
                          if (style.bgcolor) {
                              xlsxCell.s.fill = {
                                  patternType: 'solid',
                                  fgColor: { rgb: style.bgcolor.replace('#', '') }
                              };
                          }

                          // 对齐
                          xlsxCell.s.alignment = {};
                          if (style.align) xlsxCell.s.alignment.horizontal = style.align;
                          if (style.valign) xlsxCell.s.alignment.vertical = style.valign;
                          if (style.textwrap) xlsxCell.s.alignment.wrapText = true;

                          // 边框
                          if (style.border) {
                              xlsxCell.s.border = {};
                              ['top', 'bottom', 'left', 'right'].forEach(side => {
                                  if (style.border[side]) {
                                      const [borderStyle, borderColor] = style.border[side];
                                      xlsxCell.s.border[side] = {
                                          style: borderStyle,
                                          color: { rgb: borderColor.replace('#', '') }
                                      };
                                  }
                              });
                          }
                      }

                      // 添加单元格到工作表
                      ws[cellAddress] = xlsxCell;
                  });
              });

              // 处理列宽
              if (data.cols) {
                  ws['!cols'] = [];
                  const colLen = data.cols.len || 26;

                  for (let i = 0; i < colLen; i++) {
                      if (data.cols[i] && data.cols[i].width) {
                          ws['!cols'][i] = { width: data.cols[i].width / 8 }; // 转换像素到Excel列宽
                      } else {
                          ws['!cols'][i] = { width: 8.43 }; // 默认列宽
                      }
                  }
              }

              // 处理合并单元格
              if (merges && merges.length) {
                  ws['!merges'] = [];

                  merges.forEach(merge => {
                      const [start, end] = merge.split(':');
                      const startCell = XLSX.utils.decode_cell(start);
                      const endCell = XLSX.utils.decode_cell(end);

                      ws['!merges'].push({
                          s: { r: startCell.r, c: startCell.c },
                          e: { r: endCell.r, c: endCell.c }
                      });
                  });
              }

              // 添加工作表到工作簿
              XLSX.utils.book_append_sheet(wb, ws, data.name || "Sheet1");

              return wb;
          } catch (error) {
              console.error('转换数据时出错:', error);
              return null;
          }
      }*/

    /**
     * 设置数据
     * @param {Object} data - 电子表格数据
     */
    setData(data) {
        if (!data) return

        if (!this.xs) {
            // 如果电子表格尚未初始化，保存数据以便稍后加载
            this.initialData = data
            return
        }

        try {
            // 确保数据格式正确
            let formattedData = data

            // 如果数据包含sheets数组，取第一个sheet
            if (data.sheets && Array.isArray(data.sheets) && data.sheets.length > 0) {
                formattedData = data.sheets[0]
            }

            // 确保数据有必要的属性
            if (!formattedData.rows) formattedData.rows = {}
            if (!formattedData.cols) formattedData.cols = { len: 26 }
            if (!formattedData.merges) formattedData.merges = []

            console.log("加载数据:", formattedData)
            this.xs.loadData(formattedData)
            this.triggerEvent("change", formattedData)
        } catch (error) {
            console.error("设置数据失败:", error)
            this.triggerEvent("error", { type: "setData", error })
        }
    }

    /**
     * 获取当前数据
     * @returns {Object} 电子表格数据
     */
    getData() {
        return this.xs ? this.xs.getData() : null
    }

    /**
     * 获取选中的单元格
     * @returns {Object} 选中的单元格
     */
    getSelectedCell() {
        return this.xs ? this.xs.getSelectedCell() : null
    }

    /**
     * 注册事件处理函数
     * @param {string} event - 事件名称 ('change', 'ready', 'error', 'export')
     * @param {Function} callback - 回调函数
     */
    on(event, callback) {
        if (typeof callback !== "function") {
            console.error("回调必须是函数")
            return
        }

        if (!this.eventHandlers[event]) {
            this.eventHandlers[event] = []
        }

        this.eventHandlers[event].push(callback)
        return this
    }

    /**
     * 移除事件处理函数
     * @param {string} event - 事件名称
     * @param {Function} callback - 要移除的回调函数，如果不提供则移除所有
     */
    off(event, callback) {
        if (!this.eventHandlers[event]) return this

        if (!callback) {
            this.eventHandlers[event] = []
        } else {
            this.eventHandlers[event] = this.eventHandlers[event].filter((handler) => handler !== callback)
        }

        return this
    }

    /**
     * 触发事件
     * @param {string} event - 事件名称
     * @param {*} data - 事件数据
     */
    triggerEvent(event, data) {
        if (!this.eventHandlers[event]) return

        this.eventHandlers[event].forEach((callback) => {
            try {
                callback(data)
            } catch (error) {
                console.error(`事件处理函数错误 (${event}):`, error)
            }
        })
    }

    /**
     * 销毁实例
     */
    destroy() {
        if (this.xs) {
            // x-spreadsheet没有明确的destroy方法，但我们可以清理DOM
            this.container.innerHTML = ""
            this.xs = null
        }

        if (this.fileInput && this.fileInput.parentNode) {
            this.fileInput.parentNode.removeChild(this.fileInput)
        }

        // 清理事件处理函数
        this.eventHandlers = {
            change: [],
            ready: [],
            error: [],
        }
    }
}

// 如果在浏览器环境中，将SpreadsheetEditor添加到全局对象
if (typeof window !== "undefined") {
    window.SpreadsheetEditor = SpreadsheetEditor
}

// 如果在Node.js环境中，导出SpreadsheetEditor
if (typeof module !== "undefined" && module.exports) {
    module.exports = SpreadsheetEditor
}

// 示例用法
console.log("SpreadsheetEditor 已加载。使用示例:")
console.log("const editor = new SpreadsheetEditor('#container');")
console.log("editor.importExcel(); // 导入Excel")
console.log("editor.exportExcel('data.xlsx'); // 导出Excel")
console.log("editor.on('change', data => console.log('数据已更改', data)); // 监听数据变更")

